using AgentFrameworkDemo.Models;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;

namespace AgentFrameworkDemo.Services;

/// <summary>
/// 简化的记忆管理器实现
/// </summary>
public class MemoryManager : IMemoryManager
{
    private readonly ConcurrentDictionary<string, List<MemoryItem>> _memories = new();
    private readonly ILogger<MemoryManager> _logger;

    public MemoryManager(ILogger<MemoryManager> logger)
    {
        _logger = logger;
        _logger.LogInformation("MemoryManager initialized");
    }

    public async Task SaveMemoryAsync(string agentId, MemoryItem memory)
    {
        try
        {
            var agentMemories = _memories.GetOrAdd(agentId, _ => new List<MemoryItem>());
            memory.AgentId = agentId;
            agentMemories.Add(memory);

            // 保持记忆数量限制
            if (agentMemories.Count > 1000)
            {
                agentMemories.RemoveAt(0);
            }

            _logger.LogDebug("Memory saved for agent: {AgentId}, Count: {Count}", agentId, agentMemories.Count);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to save memory for agent: {AgentId}", agentId);
            throw;
        }

        await Task.CompletedTask;
    }

    public async Task<List<MemoryItem>> SearchMemoriesAsync(string agentId, string query, int limit = 10)
    {
        try
        {
            if (_memories.TryGetValue(agentId, out var agentMemories))
            {
                // 简单的关键词搜索
                var results = agentMemories
                    .Where(m => m.Content.Contains(query, StringComparison.OrdinalIgnoreCase) ||
                                m.Tags.Any(t => t.Contains(query, StringComparison.OrdinalIgnoreCase)))
                    .OrderByDescending(m => m.Importance)
                    .ThenByDescending(m => m.CreatedAt)
                    .Take(limit)
                    .ToList();

                _logger.LogDebug("Found {Count} memories for query: {Query}", results.Count, query);
                return results;
            }

            return new List<MemoryItem>();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to search memories for agent: {AgentId}", agentId);
            return new List<MemoryItem>();
        }
    }

    public async Task<List<MemoryItem>> GetMemoriesAsync(string agentId, int limit = 50)
    {
        try
        {
            if (_memories.TryGetValue(agentId, out var agentMemories))
            {
                return agentMemories.TakeLast(limit).ToList();
            }

            return new List<MemoryItem>();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to get memories for agent: {AgentId}", agentId);
            return new List<MemoryItem>();
        }
    }

    public async Task DeleteMemoryAsync(string agentId, string memoryId)
    {
        try
        {
            if (_memories.TryGetValue(agentId, out var agentMemories))
            {
                var memory = agentMemories.FirstOrDefault(m => m.Id == memoryId);
                if (memory != null)
                {
                    agentMemories.Remove(memory);
                    _logger.LogDebug("Memory deleted: {MemoryId} for agent: {AgentId}", memoryId, agentId);
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to delete memory: {MemoryId} for agent: {AgentId}", memoryId, agentId);
        }

        await Task.CompletedTask;
    }

    public async Task CleanupOldMemoriesAsync(string agentId, TimeSpan olderThan)
    {
        try
        {
            if (_memories.TryGetValue(agentId, out var agentMemories))
            {
                var cutoffTime = DateTime.UtcNow - olderThan;
                var oldMemories = agentMemories.Where(m => m.CreatedAt < cutoffTime).ToList();

                foreach (var memory in oldMemories)
                {
                    agentMemories.Remove(memory);
                }

                _logger.LogInformation("Cleaned up {Count} old memories for agent: {AgentId}", oldMemories.Count, agentId);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to cleanup old memories for agent: {AgentId}", agentId);
        }

        await Task.CompletedTask;
    }
}